package com.bsj.power.pls.config.cached;

import com.alibaba.fastjson.JSON;
import com.bsj.power.common.def.entity.HighRise;
import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author yinhao
 * @version 1.0
 * @description 楼层高度判断
 * @date 2024/9/8
 */
@Slf4j
public class HighRiseCached {

    //key = mapId, value = 对应楼层的最小与最大高度
    private static Map<Integer, HighRise> highRiseMap = new ConcurrentHashMap<>();
    //key = 1 or 2机组, value = mapId集合
    private static Map<Integer, List<Integer>> mapIds = new ConcurrentHashMap<>();

    private static ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock();

    //mapID汇总：   更新后
    //①号机组：
    //-9.5：19       4
    //0：15          5
    //7.5：17        6
    //16：18         7
    //室外：34        8
    //②号机组：
    //室外：33        9
    //-9.5：11       10
    //0：16          11
    //7.5：6         12
    //16：10         13
    public void start() throws Exception {
        //二号机组
        //室外
        highRiseMap.put(33, HighRise.builder().riseMin(-10.5D).riseMax(-9.5D).build());
        //室内
        highRiseMap.put(11, HighRise.builder().riseMin(-9.5D).riseMax(0D).build());
        highRiseMap.put(16, HighRise.builder().riseMin(0D).riseMax(7.5D).build());
        highRiseMap.put(6, HighRise.builder().riseMin(7.5D).riseMax(16D).build());
        highRiseMap.put(10, HighRise.builder().riseMin(16D).riseMax(31D).build());
        mapIds.put(2, List.of(33, 11, 16, 6, 10));

        //一号机组
        //室外
        highRiseMap.put(34, HighRise.builder().riseMin(-10.5D).riseMax(-9.5D).build());
        //室内
        highRiseMap.put(19, HighRise.builder().riseMin(-9.5D).riseMax(0D).build());
        highRiseMap.put(15, HighRise.builder().riseMin(0D).riseMax(7.5D).build());
        highRiseMap.put(17, HighRise.builder().riseMin(7.5D).riseMax(16D).build());
        highRiseMap.put(18, HighRise.builder().riseMin(16D).riseMax(31D).build());
        mapIds.put(1, List.of(34, 19, 15, 17, 18));
        log.info("MapId加载楼层范围成功: {}", JSON.toJSONString(highRiseMap));
    }

    /**
     * 根据mapId获取楼层高度
     * @param mapId
     * @return
     */
    public static HighRise getHigh(Integer mapId) {
        rwlock.readLock().lock();
        try {
            HighRise highRise = highRiseMap.get(mapId);
            if (highRise == null) {
                return null;
            }
            return highRise;
        } finally {
            rwlock.readLock().unlock();
        }
    }

    /**
     * 根据mapId获取空间位置 - 1号机组 | 2号机组
     * @param mapId
     * @return
     */
    public static Integer getSpace(Integer mapId) {
        rwlock.readLock().lock();
        AtomicReference<Integer> space = new AtomicReference<>(0);
        try {
            mapIds.forEach((key, value) -> {
                if (value.contains(mapId)) {
                    space.set(key);
                }
            });
            return space.get();
        } finally {
            rwlock.readLock().unlock();
        }
    }

    /**
     * 获取全部mapId
     * @return
     */
    public static List<Integer> getAllMapId() {
        List<Integer> ids = new LinkedList<>();
        mapIds.forEach((k, v) -> {
            ids.addAll(v);
        });
        return ids;
    }

    /**
     * 根据机组号与楼层，获取mapId
     * @param buildNo 机组号
     * @param fool 楼层 0 = 室外, 1=-9.5m, 2=0m, 3=7.5m, 4=16m, 5=23m
     * @return
     */
    public static Integer getFloorByMapId(Integer buildNo, Integer fool) {
        List<Integer> list = mapIds.get(buildNo);
        if (list == null) {
            return null;
        }
        AtomicReference<Integer> mapId = new AtomicReference<>();
        Double fd = getFool(fool);
        list.stream().forEach(item -> {
            HighRise highRise = highRiseMap.get(item);
            if (highRise != null) {
                Double riseMin = highRise.getRiseMin();
                if (riseMin.equals(fd)) {
                    mapId.set(item);
                }
            }
        });
        return mapId.get();
    }

    /**
     * 根据楼层获取多少米层楼
     * @param fool
     * @return
     */
    private static Double getFool(Integer fool) {
        Double f = null;
        switch (fool) {
            case 0:
                //将室外设置成最小-10.5
                f = -10.5;
                break;
            case 1:
                f = -9.5;
                break;
            case 2:
                f = 0d;
                break;
            case 3:
                f = 7.5;
                break;
            case 4:
                f = 16D;
                break;
            default:
                break;
        }
        return f;
    }
}
